// Sage Android Client.
// Connect to a Sage server, remotely execute commands and display results.
//
// Copyright (C) 2010, Harald Schilly <harald.schilly@gmail.com>
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.

/**
 * 
 */

package org.sagemath.android.interacts;

import org.sagemath.android.Calculation;
import org.sagemath.android.Global;
import org.sagemath.android.R;

import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.os.Handler;
import android.os.Message;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.ImageView;
import android.widget.ScrollView;
import android.widget.TextView;
import android.widget.ImageView.ScaleType;

import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.RandomAccessFile;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URI;
import java.net.URISyntaxException;
import java.net.URL;
import java.text.DecimalFormat;

/**
 * @author Harald Schilly
 */
public class Plot extends AbstractInteract {
  /**
   * @param resource
   */
  public Plot() {
    super(R.layout.plot);
  }
  
  private ImageView plot;
  
  private Button btnZoomIn, btnZoomOut;
  
  private float zoom = 1;
  
  private final String FILENAME = "plot.png";
  
  private TextView status;
  
  private ScrollView scroll;
  
  final private static DecimalFormat decimalPercent = new DecimalFormat();
  static {
    decimalPercent.applyPattern("0.## %");
  }
  
  final private static BitmapFactory.Options bmOptions = new BitmapFactory.Options();
  
  static {
    bmOptions.inScaled = false;
  }
  
  /*
   * (non-Javadoc)
   * @see org.sagemath.android.interacts.AbstractInteract#build()
   */
  @Override
  protected void init() {
    plot = (ImageView) myView.findViewById(R.id.imgPlot);
    status = (TextView) myView.findViewById(R.id.txtPlotStatus);
    scroll = (ScrollView) myView.findViewById(R.id.plotScrollViewImage);
    
    // plot.setImageResource(R.drawable.example_plot);
    Bitmap bm = BitmapFactory.decodeResource(context.getResources(), R.drawable.example_plot,
        bmOptions);
    plot.setImageBitmap(bm);
    plot.setScaleType(ScaleType.CENTER);
    
    // TODO that does not work this way and we better not use scrolling at all
    scroll.setHorizontalScrollBarEnabled(true);
    
    btnZoomIn = (Button) myView.findViewById(R.id.btnPlotZoomIn);
    btnZoomOut = (Button) myView.findViewById(R.id.btnPlotZoomOut);
    
    OnClickListener nyi = new OnClickListener() {
      
      @Override
      public void onClick(View v) {
        if (v == btnZoomIn) {
          zoom *= Global.GOLDEN_RATIO;
        } else if (v == btnZoomOut) {
          zoom /= Global.GOLDEN_RATIO;
        }
        String width = Integer.toString(myView.getWidth());
        calculate("plot(...zoom=" + decimalPercent.format(zoom) + ", width=" + width + ")");
      }
    };
    
    btnZoomIn.setOnClickListener(nyi);
    btnZoomOut.setOnClickListener(nyi);
    
    try {
      DownloadThread dt = new DownloadThread(downloadProgressHandler, new URI(
          "http://www.example.com/"));
      dt.start();
    } catch (MalformedURLException ex) {
      
    } catch (URISyntaxException ex) {
      
    }
  }
  
  final private static int DOWNLOAD_PROGRESS = 239847;
  
  /**
   * Updates UI with download progress
   */
  final private Handler downloadProgressHandler = new Handler() {
    @Override
    public void handleMessage(Message msg) {
      switch (msg.what) {
        case (DOWNLOAD_PROGRESS):
          int down = msg.arg1;
          int size = msg.arg2;
          if (size == 0) {
            // unknown
          } else {
            String percent = decimalPercent.format((double) down / (double) size);
            if (status != null) {
              status.setText("progress " + percent);
            }
          }
          break;
        default:
          super.handleMessage(msg);
      }
    }
  };
  
  /**
   * Downloads the image
   */
  private class DownloadThread extends Thread {
    
    private static final int MAX_BUFFER = 1024;
    
    private Handler handler;
    
    private int size = 0;
    
    private URL url;
    
    int downloaded = 0;
    
    DownloadThread(Handler h, URI uri) throws MalformedURLException {
      handler = h;
      this.url = uri.toURL();
    }
    
    private void sendMessage() {
      Message msg = handler.obtainMessage();
      msg.what = DOWNLOAD_PROGRESS;
      msg.arg1 = downloaded;
      msg.arg2 = size;
      handler.sendMessage(msg);
    }
    
    @Override
    public void run() {
      RandomAccessFile file = null;
      InputStream stream = null;
      try {
        HttpURLConnection connection = (HttpURLConnection) url.openConnection();
        stream = connection.getInputStream();
        size = connection.getContentLength();
        
        if (connection.getResponseCode() != 200) {
          // TODO ERROR
        }
        
        if (size < 1) {
          // TODO ERROR
        }
        
        File f = new File(FILENAME);
        if (f.exists()) {
          f.delete();
        }
        f.deleteOnExit();
        file = new RandomAccessFile(FILENAME, "rw");
        
        while (true) {
          byte buffer[] = new byte[(size - downloaded > MAX_BUFFER) ? MAX_BUFFER : size
              - downloaded];
          
          // Read from server into buffer.
          int read = stream.read(buffer);
          if (read == -1) {
            break;
          }
          
          // Write buffer to file.
          file.write(buffer, 0, read);
          downloaded += read;
          sendMessage();
        }
        
      } catch (IOException ex) {
        
      }
    }
  } // ~~~ end DownloadThread
  
  /*
   * (non-Javadoc)
   * @see
   * org.sagemath.android.interacts.AbstractInteract#onError(java.lang.String)
   */
  @Override
  protected void onError(String msg) {
    status.setText(msg);
  }
  
  /*
   * (non-Javadoc)
   * @see
   * org.sagemath.android.interacts.AbstractInteract#onResult(java.lang.String)
   */
  @Override
  protected void onResult(Calculation c) {
    status.setText(c.getCode() + "\n" + c.getResult());
  }
  
  /*
   * (non-Javadoc)
   * @see org.sagemath.android.interacts.AbstractInteract#reset()
   */
  @Override
  public void reset() {
    zoom = 1;
    status.setText("reset");
  }
}
